package com.whjz.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.whjz.entity.MbRequestLog;
import com.whjz.redis.RedisUtils;
import com.whjz.services.RequestService;
import com.whjz.services.UserService;
import com.whjz.utils.ConstansUtil;
import com.whjz.utils.DateUtils;
import com.whjz.utils.StringConstantUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.*;

/**
 * @author liweibin 返回值拦截处理 add by liweibin for (TASK)95所有接口返回值除了业务数据还要添加token数据
 *         20181127
 */
@Component
@Slf4j
public class ResponseFilter extends ZuulFilter {

	@Autowired
	private UserService UserService;

	@Autowired
	private RequestService requestService;
	/**
	 * pre 可以在请求被路由之前调用 route 在路由请求时被调用 post 在route和error过滤之后被调用 error 处理请求时发生错误时被调用
	 * 
	 * @return
	 */
	@Override
	public String filterType() {
		return "post"; // 在route和error过滤之后被调用
	}

	@Override
	public int filterOrder() {
		return 0; // 执行顺序 数字越大级别越低
	}

	@Override
	public boolean shouldFilter() {
		return true;
	}

	@Override
	public Object run() {
		/*log.info("=================>本次访问进入网关返回结果记录时间"+System.currentTimeMillis());*/
		RequestContext ctx = RequestContext.getCurrentContext();
		HttpServletRequest request = ctx.getRequest();
		MultipartHttpServletRequest multipartRequest=null;
		JSONObject reqJsonObj = new JSONObject() ;
		JSONObject jsonObj = null;
		Map<String,String> baseInfoMap = null;
		try {
			String contentType  =  request.getContentType();
			if(org.apache.commons.lang3.StringUtils.isNotBlank(contentType) && contentType.contains("multipart")){
				// 将request转为MultipartHttpServletRequest，从而使用getParameter(key)方法获取指定的值
				HttpServletRequest httpRequest = (HttpServletRequest) request;
				contentType = httpRequest.getContentType();
				MultipartResolver resolver = new CommonsMultipartResolver(httpRequest.getSession().getServletContext());
				multipartRequest = resolver.resolveMultipart(httpRequest);
				request = multipartRequest;
			}
			if(request.getRequestURI().contains("manage")||request.getRequestURI().contains("workstation") || request.getRequestURI().contains("common")) {

					//在如下过滤器中，上传文件中的content-type:multipart/form-data使用获取request.getParameter(key)无法获取相应的值。
					// 需要借助Spring框架中的CommonsMultipartResolver.resolveMultipart(HttpServletRequest request)

				String reqBody = StreamUtils.copyToString((InputStream) request.getInputStream(), Charset.forName("UTF-8"));
				/** mod by liweibin for (BUG)358 图片下载失败  20181220 begin */
				// 文件上传不处理,没有入参不处理
				if (StringUtils.isBlank(reqBody) || reqBody.contains("form-data")) {
					// reqBody = multipartRequest.getParameterMap().values().toString();
					Map<String, String> tempMap = new HashMap<String, String>();
					Map<String, String[]> reqMap = multipartRequest.getParameterMap();
					Set<Map.Entry<String, String[]>> set = reqMap.entrySet();
					Iterator<Map.Entry<String, String[]>> it = set.iterator();
					while (it.hasNext()) {
						Map.Entry<String, String[]> entry = it.next();
						System.out.println("KEY:"+entry.getKey());
						for (String str : entry.getValue()) {
							System.out.println(str);
							tempMap.put(entry.getKey(), str);
						}
					}
					String logseq = ctx.getZuulRequestHeaders().get("logseq");
					tempMap.put("logseq",logseq);
					reqBody = JSON.toJSONString(tempMap);
				}
				try {
					reqJsonObj =JSONObject.parseObject(reqBody);		//数据格式化
				} catch (Exception e) {
					e.printStackTrace();		//格式化异常
					return null;
				}
				//GET请求没数据
				if(reqJsonObj == null) {
					return null;
				}
				//reqJsonObj.putAll(baseInfoMap);

				//签名校验
//            try {
//                String sign = request.getHeader("X-Mgs-Proxy-Signature");//移动网关传过来的签名
//                String salt ="1638b3f3b90c4829aabdaa7db94bfb3c";     //MD5 Salt
//                String stringToSign = getStringToSign(request, reqBody);
//                MessageDigest digest = MessageDigest.getInstance("MD5");
//                String toSignedContent = stringToSign + salt;
//                byte[] content = digest.digest(toSignedContent.getBytes("UTF-8"));
//                String computedSign = Hex.encodeHexString(content);
//                boolean isSignLegal = Objects.equals(sign, computedSign);
//                log.info("签名匹配: "+stringToSign+" : "+isSignLegal);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }

				//添加消费方交易号
				reqJsonObj.put("beginTime", String.valueOf(new Date().getTime()));		//请求开始时间   add by liweibin for (BUG)488我的卡包里面下挂失败     (TASK)141 完整app请求流水日志  20181218 begin

				String responseStr = StreamUtils.copyToString((InputStream) ctx.getResponseDataStream(), Charset.forName("UTF-8"));

				/** mod by liweibin for (BUG)358 图片下载失败  20181220 end */

				if (StringUtils.isNotBlank(reqBody) && StringUtils.isNotBlank(responseStr)) {
					/** mod by zhangxueliang for(bug) 320 登录超时之后再点击登录无法正常登录 20181207 begin*/
					// 登录和注册不用验证token

					jsonObj = JSONObject.parseObject(responseStr); // 参数对象格式化
					ctx.setResponseBody( JSONObject.toJSONString(jsonObj, SerializerFeature.WriteNullStringAsEmpty));
					//luboyu 当jsonObj为null的时候不做处理
					if (null != jsonObj) {
						//判断code是否为200 ，非200时清空
						/*log.info("=================>本次访问进入网关j储存日志记录时间开始"+System.currentTimeMillis());*/
//						RequestLog requestLog = new RequestLog();
						MbRequestLog requestLog=new MbRequestLog();
						boolean flag = addRequestLog(requestLog, reqJsonObj.toString(), jsonObj.toJSONString(), request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+request.getRequestURI());
						/*log.info("=================>本次访问进入网关j储存日志记录时间结束"+System.currentTimeMillis());*/
						log.info("\n请求记录结果为：" + flag + ";记录信息： " + JSONObject.toJSONString(requestLog));
						/*log.info("=================>本次访问进入网关记录时间结束"+System.currentTimeMillis());*/
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return null;
	}
	
	
	/** add by liweibin for (TASK)141 完整app请求流水日志  20181218 begin */
	/**
	 * 添加交易流水日志
	 * @param requestLog  	日志对象
	 * @param reqBody		请求体
	 * @param responseStr	响应体
	 * @param requestURI	请求URL
	 * @return
	 */
	private boolean addRequestLog(MbRequestLog requestLog, String reqBody, String responseStr, String requestURI) {
		JSONObject resuestObj = JSONObject.parseObject(reqBody);		//交易体json对象
		JSONObject responseObj = JSONObject.parseObject(responseStr); 	//响应体json对象
		long endTime = new Date().getTime();		//请求结束时间
		long timing = endTime - resuestObj.getLongValue("beginTime");	//请求用时
		requestLog.setBackSeqNo(RedisUtils.getValue(StringConstantUtil.BACK_SEQ+resuestObj.getString("custNo")));
		//重置后台流水号
		RedisUtils.setKey(StringConstantUtil.BACK_SEQ+resuestObj.getString("custNo"),"");
		requestLog.setRequestParameters(reqBody);			//请求体
		requestLog.setResponseResult(responseStr);			//响应结果
		requestLog.setTime(String.valueOf(timing));			//耗时
		requestLog.setRequestUrl(requestURI);				//接口请求
		requestLog.setCreateDate(DateUtils.getCurDate("yyyyMMdd")); //创建时间
		requestLog.setUpdateDate(DateUtils.getCurDateTime()); //更新时间
		requestLog.setResponseStatus(responseObj.getString("code"));			//响应状态
		requestLog.setConsumerSeqNo(resuestObj.getString("seqNo"));		//交易列号
		//不知道谁写的，前端流水号，前端传过来的。这里认领一下，看是不是要删除
		/*if(resuestObj.containsKey("logseq")){
			requestLog.setConsumerSeqNo(resuestObj.getString("logseq"));		//交易列号
		}
		if(resuestObj.containsKey("nmpBussinessNo")){
			requestLog.setConsumerSeqNo(resuestObj.getString("nmpBussinessNo"));		//交易列号
		}*/
//		requestLog.setOperateUser(resuestObj.getString("userId"));			//操作用户
		requestLog.setOperateUser(resuestObj.getString("custNo"));			//操作用户 应该取custNo
		requestLog.setChannel(ConstansUtil.CHANNEL_NARMAL);		//普通渠道
		//判断渠道（01普通、02语音、03视频）
		if(StringUtils.isNotBlank(resuestObj.getString("sessionId")) && StringUtils.isNotBlank(resuestObj.getString("seqNo"))) {
			requestLog.setChannel(ConstansUtil.CHANNEL_TELLER);		//视屏
		}
		if(StringUtils.isNotBlank(resuestObj.getString("voiceFlag")) && resuestObj.getBoolean("voiceFlag")) {
			requestLog.setChannel(ConstansUtil.CHANNEL_VOICE);		//语音
		}		
		//消费者ID 3-后管 2-pad
		if("3".equals(resuestObj.getString("sourceType"))){
			requestLog.setRequestSource("back-zuul");
		}else{
			requestLog.setRequestSource("app-zuul");
		}

		/** add by linliangze 20190215 begin */
		/*log.info("================起始时间：" + resuestObj.getLongValue("beginTime"));*/
	
		/**针对后管服务 无 【beginTime】特殊处理**/
		if (resuestObj.getLongValue("beginTime")==0) {
			requestLog.setTime(String.valueOf(0L));			//耗时
		}
		/*log.info("================结束时间：" + endTime);*/
		log.info("================耗时：" + String.valueOf(timing));

		// 关键字段做掩码
		log.info("================请求体RequestLog为：" + JSONObject.toJSONString(requestLog));

		/** add by linliangze 20190215 end */
//		return baseServiceScheduler.addRequestLog(requestLog);
		Map result = requestService.addRequestLog(requestLog);
		Boolean addRequestLog = false;
		if ("200".equals(result.get("code"))) {
			return addRequestLog = true;
		}
		return addRequestLog;
	}
	/** add by liweibin for (TASK)141 完整app请求流水日志  20181218 end */
}